/* complete.c, Ait Emacs, Kevin Bloom, BSD 3-Clause, 2023 */

#include "header.h"
#include "termbox.h"

/* basic filename completion, based on code in uemacs/PK */
int getfilename(char *prompt, char *buf, int nbuf)
{
  static char temp_file[] = TEMPFILE;
  int cpos = 0;  /* current character position in string */
  int k = 0, c, fd, didtry, iswild = 0, start_col = strlen(prompt);
  struct tb_event ev;
  char sys_command[255];
  FILE *fp = NULL;
//  buf[0] ='\0';
  cpos = strlen(buf);

  display_prompt_and_response(prompt, buf);
  for (;;) {
    didtry = (k == 0x09);  /* Was last command tab-completion? */
    tb_present();
    if(tb_poll_event(&ev) != TB_OK) return 0;

    if(msgline_editor(ev, prompt, buf, &cpos)) {
      k = 0;
      continue;
    }

    if(!ev.mod)
      k = ev.ch;
    else
      k = ev.key;

    if (k < 32 &&
        k != TB_KEY_CTRL_G &&
        k != TB_KEY_BACKSPACE &&
        k != TB_KEY_BACKSPACE2 &&
        k != TB_KEY_ENTER &&
        k != TB_KEY_CTRL_R &&
        k != TB_KEY_CTRL_S &&
        k != TB_KEY_ESC &&
        k != TB_KEY_CTRL_I &&
        k != TB_KEY_TAB)
      continue;

    switch(k) {
    case TB_KEY_CTRL_J: /* cr, lf */
    case TB_KEY_ENTER:
      if (cpos > 0 && NULL != strchr(buf, '~')) goto do_tab;
    case TB_KEY_CTRL_G: /* ctrl-g, abort */
      if (fp != NULL) fclose(fp);
      tb_set_cursor(0, MSGLINE);
      clrtoeol("", MSGLINE);
      return (k != 0x07 && cpos > 0);

    case TB_KEY_CTRL_U: /* C-u kill */
      cpos = 0;
      buf[0] = '\0';
      break;

do_tab:
    case TB_KEY_TAB: /* TAB, complete file name */
      /* scan backwards for a wild card and set */
      iswild=0;
      while (cpos > 0) {
        cpos--;
        if (buf[cpos] == '*' || buf[cpos] == '?')
          iswild = 1;
      }

      /* first time retrieval */
      if (! didtry) {
        if (fp != NULL) fclose(fp);
        strcpy(temp_file, TEMPFILE);
        if (-1 == (fd = mkstemp(temp_file)))
          fatal("%s: Failed to create temp file\n");
        strcpy(sys_command, "echo ");
        strcat(sys_command, buf);
        if (!iswild) strcat(sys_command, "*");
        strcat(sys_command, " >");
        strcat(sys_command, temp_file);
        strcat(sys_command, " 2>&1");
        (void) ! system(sys_command); /* stop compiler unused result warning */
        fp = fdopen(fd, "r");
        unlink(temp_file);
      }

      /* copy next filename into buf */
      while ((c = getc(fp)) != EOF && c != '\n' && c != ' ')
        if (cpos < nbuf - 1 && c != '*')
          buf[cpos++] = c;

      buf[cpos] = '\0';
      for(int i = cpos+1; buf[i] != '\0'; i++)
        buf[i] = 0;
      if (c != ' ') rewind(fp);
      didtry = 1;
      tb_set_cursor(start_col, MSGLINE);
      clrtoeol(prompt, MSGLINE);
      addstr(buf);
      break;

    default:
      if (cpos < nbuf - 1) {
        for(int i = strlen(buf); i > cpos; i--) {
          buf[i] = buf[i - 1];
        }
        buf[cpos] = k;
        buf[strlen(buf)] = '\0';
        tb_set_cursor(start_col, MSGLINE);
        addstr(buf);
        cpos++;
        tb_set_cursor(start_col + cpos, MSGLINE);
      }
      break;
    }
  }
}

buffer_t * getbuffername(char *prompt, char *buf, int nbuf, int *ret)
{
  int cpos = 0;  /* current character position in string */
  int k = 0, c, i, didtry = 0;
  int start_col = strlen(prompt);
  struct tb_event ev;
  buffer_t *bp = NULL;
  char tabbuffer[NAME_MAX];
  buf[0] ='\0';
  cpos = strlen(buf);

  display_prompt_and_response(prompt, buf);
  for (;;) {
    didtry = (k == 0x09) ? didtry + 1 : 0;  /* Was last command tab-completion? */
    tb_present();
    if(tb_poll_event(&ev) != TB_OK) return 0;

    if(msgline_editor(ev, prompt, buf, &cpos)) {
      k = 0;
      continue;
    }

    if(!ev.mod)
      k = ev.ch;
    else
      k = ev.key;

    switch(k) {
    case TB_KEY_CTRL_J: /* cr, lf */
    case TB_KEY_ENTER:
      *ret = 1;
      return bp;
    case TB_KEY_CTRL_G: /* ctrl-g, abort */
      tb_set_cursor(0, MSGLINE);
      clrtoeol("", MSGLINE);
      return NULL;

    case TB_KEY_BACKSPACE2: /* del, erase */
    case TB_KEY_BACKSPACE: /* backspace */
      if (cpos == 0) continue;
      buf[--cpos] = '\0';
      tb_set_cursor(start_col + cpos, MSGLINE);
      addch(' ');
      tb_set_cursor(start_col + cpos, MSGLINE);
      break;

    case TB_KEY_CTRL_U: /* C-u kill */
      cpos = 0;
      buf[0] = '\0';
      break;

    case TB_KEY_TAB: /* TAB, complete file name */
      if(didtry == 0)
        strncpy(tabbuffer, buf, NAME_MAX);
      for (c = 0, bp = bheadp; bp != NULL; bp = bp->b_next) {
        int match = FALSE;
        if(tabbuffer[0] == '\0') {
          if (didtry == c) {
            strncpy(buf, bp->b_bname, NAME_MAX);
            break;
          }
          c++;
        }
        for(i = 0; i < strlen(tabbuffer); i++)
          if(tabbuffer[i] == bp->b_bname[i]) {
            match = TRUE;
          } else {
            match = FALSE;
            break;
          }
        if(match) {
          if(didtry == c) {
            strncpy(buf, bp->b_bname, NAME_MAX);
            break;
          }
          c++;
        }
      }
      cpos = 0;
      cpos += strlen(buf);
      buf[cpos] = '\0';
      for(int i = cpos+1; buf[i] != '\0'; i++)
        buf[i] = 0;
      tb_set_cursor(start_col, MSGLINE);
      clrtoeol(prompt, MSGLINE);
      addstr(buf);
      break;

    default:
      if (cpos < nbuf - 1) {
        for(int i = strlen(buf); i > cpos; i--) {
          buf[i] = buf[i - 1];
        }
        buf[cpos] = k;
        tb_set_cursor(start_col, MSGLINE);
        addstr(buf);
        cpos++;
        tb_set_cursor(start_col + cpos, MSGLINE);
      }
      break;
    }
  }
}
